<?php
class _Mail {
  var $to = '';
  var $from = '';
  var $subject = '';
  var $body = '';
  
  var $host = '';
  var $username = '';
  var $password = '';
  var $mail_name = '';
  
  var $Error = '';
  var $Debug_mode = '';
  
  function __construct() {
    require("mail.conf.php");
    $this->host = $MAILHOST;
    $this->username = $MAILUSERNAME;
    $this->password = $MAILPASSWORD;
    $this->from = $MAILFROM;
    $this->mail_name = $MAILNAME;
    $this->Debug_mode = $MAILDEBUG;
  }
  
  function Sendmail() {
    if(strlen($this->to) < 5 || strlen($this->from) < 5 || strlen($this->subject) < 5 || strlen($this->body) < 5) {
      $this->Error ="Mail input not valid";
      return false;
    }
    
    $mail = new SMTPMailer();
    
    $mail->Host = $this->host;
    $mail->Username = $this->username;
    $mail->Password = $this->password;
    
    $mail->To = $this->to;
    $mail->From = $this->from;
    $mail->Subject = $this->subject;
    $mail->Body = $this->body;
    $mail->MailName = $this->mail_name;
    
    $mail->debug_mode = $this->Debug_mode;

    if(!$mail->Send()) {
      $this->Error = "Message was not sent. {$mail->ErrorInfo}";
      return false;
    }
    return true;
  }
}

class SMTPMailer {
  
  var $Host = '';
  var $Username = '';
  var $Password = '';
  var $Port = 25;
  
  var $From = '';
  var $To = '';
  var $Subject = '';
  var $Body = '';
  var $MailName = '';
  
  var $smtp = false;
  var $ErrorInfo = false;
  
  var $debug_mode = false;
  
  function Send() {
    if($this->debug_mode) echo "<small><b><i>[DEBUG MODE is ON]</i></b></small><br />";
    
    if(!$this->connectSmtpServer()) return false;
    
    # sometimes the SMTP server takes a little longer to respond
    # so we will give it a longer timeout for the first read
    // Windows still does not have support for this timeout function
    if(substr(PHP_OS, 0, 3) != "WIN")
     socket_set_timeout($this->smtp, 30, 0);
     
    $this->getReplyCode($this->smtp); // Get invite message from server
    
    if(!$this->sendCommand($this->smtp, "EHLO {$this->Host}\r\n")) { // Send HELO to server
        if(!$this->sendCommand($this->smtp, "HELO {$this->Host}\r\n")) {
          if(!$this->ErrorInfo) $this->ErrorInfo = "HELO rejected from server.";
          return false;
        }
      }
      
    $cmdreply = $this->sendCommand($this->smtp, "AUTH LOGIN\r\n"); // Ignite Authentication
    if(!$cmdreply) return false;
    elseif($cmdreply != 334) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "Authentication not supported on server.";
      return false;
      }
      
    $cmdreply = $this->sendCommand($this->smtp, base64_encode($this->Username)."\r\n"); // Send Username
    if(!$cmdreply) return false;
    elseif($cmdreply != 334) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "Username not accepted from server.";
      return false;
    }
    
    $cmdreply = $this->sendCommand($this->smtp, base64_encode($this->Password)."\r\n"); // Send Password
    if(!$cmdreply) return false;
    elseif($cmdreply != 235) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "Password not accepted from server.";
      return false;
    }
    
    $cmdreply = $this->sendCommand($this->smtp, "MAIL FROM: \"{$this->MailName}\"<{$this->From}>\r\n"); // Mail From
    if(!$cmdreply) return false;
    elseif($cmdreply != 250) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "'Mail from' not accepted from server.";
      return false;
    }
    
    $cmdreply = $this->sendCommand($this->smtp, "RCPT TO: <{$this->To}>\r\n"); // Mail to
    if(!$cmdreply) return false;
    elseif($cmdreply != 250 && $cmdreply != 251) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "'Mail to' not accepted from server.";
      return false;
    }
    
    $cmdreply = $this->sendCommand($this->smtp, "DATA\r\n"); // Data
    if(!$cmdreply) return false;
    elseif($cmdreply != 354) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "Data not accepted from server.";
      return false;
    }
    
    $cmdreply = $this->sendCommand($this->smtp, "To: <{$this->To}>\r\nFrom: <{$this->From}>\r\nSubject: {$this->Subject}\r\n\r\n\r\n{$this->Body}\r\n.\r\n"); // Mail Data
    if(!$cmdreply) return false;
    elseif($cmdreply != 250) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "'Mail data' not accepted from server.";
      return false;
    }
    
    $cmdreply = $this->sendCommand($this->smtp, "QUIT\r\n"); // Quit connection
    if(!$cmdreply) return false;
    elseif($cmdreply != 221) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "Server rejected quit command.";
      return false;
    }
    
    $this->disconnectSmtpServer($this->smtp);
    return true;
  }
  
  function connectSmtpServer () {
    if($this->smtp) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "Server already connected.";
      return false;
    }
    $smtpconnection = fsockopen($this->Host, $this->Port, $errno, $errstr, 30);
    if(!$smtpconnection) {
      if(!$this->ErrorInfo) $this->ErrorInfo = "Failed to connect to server. $errstr ($errno)";
      return false;
    }
    $this->smtp = $smtpconnection;
    if($this->debug_mode) echo "<small><b>[Connected]</b></small><br />";
    return true;
  }
  
  function disconnectSmtpServer($smtpconnection) {
    if($smtpconnection) {
      # close the connection and cleanup
      fclose($smtpconnection);
      if($this->debug_mode) echo "<small><b>[Disconnected]</b></small><br />";
      $this->smtp = false;
    }
  }
  
  function isConnected($smtpconnection) {
    if($smtpconnection) {
      $sock_status = socket_get_status($smtpconnection);
      if($sock_status["eof"]) {
        # hmm this is an odd situation... the socket is
        # valid but we are not connected anymore
        if(!$this->ErrorInfo) $this->ErrorInfo = "Odd situation! Socket valid, but not connected anymore!";
        $this->disconnectSmtpServer($smtpconnection);
        return false;
      }
      return true; # everything looks good
    }
    return false;
  }
  
  function sendCommand($smtpconnection, $command) {
    if($this->debug_mode) echo "<small>Command: <font color=\"blue\">".htmlentities($command)."</font><br /></small>";
    if($this->isConnected($smtpconnection)) {
      fputs($smtpconnection, $command);
      return $this->getReplyCode($smtpconnection);
    }
    if(!$this->ErrorInfo) $this->ErrorInfo = "Command [$command] sent without being connected to server.";
    return false;
  }
  
  function getReplyCode($smtpconnection) {
    $data = "";
    while($str = @fgets($smtpconnection,515)) {
      $data .= $str;
      # if the 4th character is a space then we are done reading
      # so just break the loop
      if(substr($str,3,1) == " ") { break; }
    }
    if($this->debug_mode) echo "<small>Server Reply: <font color=\"red\">".htmlentities($data)."</font><br /></small>";
    return substr($data,0,3);
  }
}
?> 
